package com.lion.common.spring.config;

import com.lion.common.spring.enhancers.advices.SmartMessageConverter;
import com.lion.common.spring.enhancers.header.HttpHeaderArgumentResolver;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

/**
 * <p>
 * 配置类,注册web层相关组件
 * </p>
 *
 * @author Patrick
 * @since 2024-07-02
 */
@Configuration
public class CommonWebMvcConfig implements WebMvcConfigurer {

    /**
     * 设置静态资源映射
     *
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 添加静态资源映射规则
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
        //配置 knife4j 的静态资源请求映射地址
        registry.addResourceHandler("/doc.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

    /**
     * 配置路径匹配
     * 解决接口全局添加前缀的问题
     * 但是放开openapi资源
     *
     * @param configurer
     */
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        // 接口全局添加前缀,但是放开openapi资源
        configurer.addPathPrefix("/api", aClass -> aClass.isAnnotationPresent(RestController.class) &&
                !aClass.getName().startsWith("org.springdoc"));
    }

    /**
     * 配置消息转换器
     * 解决基本数据类型无法用ValueResult包裹的问题
     *
     * @param converters initially an empty list of converters
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 保留所有默认转换器，只移除String转换器
        converters.removeIf(c -> c instanceof StringHttpMessageConverter);

        // 确保Jackson转换器存在（用于@RequestBody解析）
        if (converters.stream().noneMatch(c -> c instanceof MappingJackson2HttpMessageConverter)) {
            converters.add(new MappingJackson2HttpMessageConverter());
        }

        // 添加智能转换器（最高优先级）
        converters.add(0, new SmartMessageConverter());
    }

    /**
     * 配置参数解析器
     * 解决从HttpRequest数据类型中分离出HttpHeader并赋值给显式声明的HttpHeader参数的问题
     *
     * @param resolvers initially an empty list
     */
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        List<HttpMessageConverter<?>> converters =
                new RestTemplate().getMessageConverters();

        resolvers.add(new HttpHeaderArgumentResolver(converters));
    }
}


